--[[
	机器人管理
]]

local Timer = require("Timer")
local skynet = require("skynet")
local table_def                        = require "table_def"
local math_random = math.random
local table_copy = table.copy
local table_remove = table.remove
local string_split = string.split
local math_floor = math.floor
local table_insert = table.insert
local table_sort = table.sort

local RobotManager = class("RobotManager")

function RobotManager:ctor(message_dispatch)
	self.robot_client_fd = -1
	self.message_dispatch = message_dispatch
	self.message_list = {}
    self.total_coins_list = {}
    self.robot_pool = {} --机器人池
    self.robot_list = {} --机器人列表    
    self.vip_list = {} --放vip机器人uid
    self.delay = 0
    self.show_vip_time = math_random(30, 120) --一定时间内弹出一个机器人入场

	self:register()
end

---------------------------------------------------------
-- CMD
---------------------------------------------------------
function RobotManager:start()
    --dbglog("RobotManager start 1")
	self.user_manager = global.user_manager
	self.room_config = global.room_config
	self.rule = global.rule
	self.desk = global.desk
    self.game_name = global.game_name
    self.module_robot = self.game_name .. ".Robot" --文件路径
    --dbglog("RobotManager start 2")
	self.server_id = self.room_config:getServerId()
 	self.table_id = self.room_config:getTableId()
 	self.table_type = self.room_config:getTableType()
 	self.table_gid = self.room_config:getTableGid()
 	self.game_type = self.room_config:getGameType()
 	self.table_pattern = self.room_config:getTablePattern()	
 	self.room_data = self.room_config:getRoomData()		
 	self.robot_data = self.room_config:getRobotData()

 	self.robot_type = self.room_data.robot_type  --ebg_normal
    self:createRobot(60) 
 	self:loadRobot()
    self.timer = Timer.new(50) --0.5秒一次
    local callback = function ()
        --停止下注      
        self:update(0.5)
        return true --true 才会继续走loop
    end    
    self.timer:register(1, callback, true)    
    --dbglog("RobotManager start 5")
end

--桌子消息返回
function RobotManager:robotMessage(uid, name, ...)
	if self.message_list[uid] then 
		local callback = self.message_list[uid][name]
        if callback then           
            callback(...)
        else
            errlog("________robotMessage_未监听事件__", name)
        end        
	end		
end

--robot注册监听消息
function RobotManager:registerMessage(uid, name, callback)
    if not uid then 
        return 
    end
	if not self.message_list[uid] then 
		self.message_list[uid] = {}
	end
	self.message_list[uid][name] = callback
end

---------------------------------------------------------
-- Private
---------------------------------------------------------
function RobotManager:register()
	self.message_dispatch:register('robot_message', handler(self,self.robotMessage)) 
	
end

function RobotManager:dispatch(message_name, uid, fd, data)
    local function send()
        self.message_dispatch:dispatchSelfMessage(message_name, uid, fd, data)
    end
    local ok , err = xpcall(send, debug.traceback)
    if not ok then 
        errlog("________RobotManager__", err)
    end
end

function RobotManager:getLoadRobotInfo()
    local robot_type_list = self.room_config:getRobotTypeList() --配置列表 
    local robot_num_map = {} --当前机器人各个类型的人数
    local user_list = self.user_manager:getUserList()
    for uid, user in pairs(user_list) do          
        if user:isRobot() then           
            local robot_type_id = user:getRobotTypeId()
            if not robot_type_id then 
                errlog("________robot_type_id___", robot_type_id)
            end         
            robot_num_map[robot_type_id] = (robot_num_map[robot_type_id] or 0) + 1
        end
    end
    -- print("____robot_type_list____",  robot_type_list)
    local load_list = {} --期望加载的个数
    for id, data in pairs(robot_type_list) do
        local robot_num = string_split(data.count_range, ',')
        local coins_limit = string_split(data.coins_range, ',')
        local robot_min = tonumber(robot_num[1]) or 0
        local robot_max = tonumber(robot_num[2]) or 0
        local count = math_random(robot_min, robot_max)
        local curr_count = robot_num_map[id] or 0
        if count > curr_count then
            load_list[id] = {
                count = count - curr_count,
                coins_limit = {tonumber(coins_limit[1] or 0), tonumber(coins_limit[2]) or 0},
            }                            
        end
    end
    return load_list
end

function RobotManager:getLoadRobotInfoHbsl()
    local curr_count = 0 --当前机器人各个类型的人数
    local user_list = self.user_manager:getUserList()
    for uid, user in pairs(user_list) do          
        if user:isRobot() then           
            -- local robot_type_id = user:getRobotTypeId()
            curr_count = curr_count + 1
        end
    end

    local load_list = {} --期望加载的个数
    local robot_num = string_split(self.robot_data.count_range, ',')
    local coins_limit = string_split(self.robot_data.coins_range, ',')
    local robot_min = tonumber(robot_num[1]) or 0
    local robot_max = tonumber(robot_num[2]) or 0
    local count = math_random(robot_min, robot_max)
    load_list[1] = {
        count = count - curr_count,
        coins_limit = {tonumber(coins_limit[1] or 0), tonumber(coins_limit[2]) or 0},
    } 
    return load_list
end

--加载机器人
function RobotManager:loadRobot()
    self.room_data = self.room_config:getRoomData()
    local room_data = self.room_data
    if not room_data  then
        errlog('load_robot fail because room_data is nil or not open_robot')
        return
    end
    -- errlog("_room_data.open_robot_______", room_data.open_robot, self.room_config:getGameType())
    if not room_data.open_robot then --关闭了机器人
    -- if true then 
        for uid, robot in pairs(self.robot_list) do
            if not robot:isClose() then 
                robot:leaveReq()
            end
        end
        dbglog("______room_data____close__robot_____________")
        return 
    end
    local robot_type = room_data.robot_type  --baijiale_normal
    -- ["count_range"] = "5,10", 人数范围
    -- ["coins_range"] = "1000,10000", 金币范围
    -- ["system_bet_min"] = 10000, 下注下限
    -- ["system_last_bet_rate"] = 2, 上局下注倍数
    -- ["system_bet_area"] = "100,0,0,0,0,0,0,0", 下注倍数范围
    -- ["bet_area_float"] = "85-125", 区域下注浮动值(百分比)
    -- ["vip_seat_rate"] = 10, 上座率(百分比)
    -- ["leave_rate"] = 80,    离桌率(百分比)
    self.robot_data = self.room_config:getRobotData()
    if not self.robot_data then
        errlog('load_robot fail because robotdata is nil')
        return
    end
    --当前人数超过桌子总人数 把号放回robog_mgr节点
    if self.user_manager:getLeftUserNum() <= 0 then
        self:reset()
        return
    end

    local load_list = {} --期望加载的个数
    dbglog("self.game_type",self.game_type)
    if self.game_type == table_def.GAME_TYPE_HONGBAO then --红包扫雷特殊处理
        load_list = self:getLoadRobotInfoHbsl()
        dbglog("hbsl load_list:",tostring_r(load_list))
    else
        load_list = self:getLoadRobotInfo()
    end

    if not next(load_list) then 
       -- errlog("RobotManager加载机器人数为0 ", self:getRobotNum() )
       self:reset()
       return
    end
    --向robot_mgr节点请求机器人列表
    local ok, succ, ret_map = R().robotmgr(1):call(".msg_handler", "get_robot_type_list", load_list, robot_type)
    if not ok or not succ or not ret_map then
        errlog("load rebot is fail because succ is nil")
        self:reset()
        return
    end
    --当前人数超过桌子总人数 把号放回robog_mgr节点
    if self.user_manager:getLeftUserNum() <= 0 then
        R().robotmgr(1):send('.msg_handler', 'put_back_robots', ret_map)
        self:reset()
        return
    end
    -- dbglog("__加载机器人______ret_map___________", ret_map)
    local curr_time = os.time()    
    for _, robot_info in pairs(ret_map) do
        local uid = robot_info.uid
        local base_data = {
        	uid = uid,
        	coins = robot_info.coins,			
			vip_level = robot_info.vip_level or 0,	       	
        }
        local enter_data = {
        	name = robot_info.name,
        	icon = robot_info.icon,
        	sex = robot_info.sex,
        	icon_border = robot_info.icon_border,
        }
 		local ok, err_code = self.user_manager:addRobot(base_data, enter_data)
 		local user = self.user_manager:getUser(uid)
        user:setIsRobot(true) --是机器人
 		user:setRobotTypeId(robot_info.coins_type) --类型id
 		user:setFD(self.robot_client_fd)
 		user:setDisconnect(false) --断线标识
        local robot = self:getRobot() --从池中取一个机器人
        if robot then 
            robot:init(uid)        
        end
        self.robot_list[uid] = robot
        -- print("________robot_info.vip_level___", robot_info.vip_level)
        if user:getVipLevel() > 0 then 
            if #self.vip_list < 30 then 
                table_insert(self.vip_list, uid)
                -- print("________self.vip_list___", #self.vip_list, uid)
            end
        end
    end   
    self.desk:ntMatchsvrTableStats() --回传状态给newmatchsvr

    self:reset()
    dbglog("__加载机器人______结束_____1____", self:getRobotNum())
end

--
function RobotManager:getRobotNum()    
    local num = 0
    for uid, robot in pairs(self.robot_list) do 
        if not robot:isClose() and not robot:isBanker() then 
            num = num + 1
        end
    end    
    return num
end

function RobotManager:reset() 

    self:sortRobot()
    if self.game_type == table_def.GAME_TYPE_HONGBAO then return end
    -- self:setTotalCoins()
end

--创建机器人
function RobotManager:createRobot(num)    
    
    local Robot = import(self.module_robot)      
    for i=1, num do   
        local robot = Robot.new(self)                
        table_insert(self.robot_pool, robot)
    end
end

--从池中取一个机器人
function RobotManager:getRobot()    
    for i=1, #self.robot_pool do   
        local robot = self.robot_pool[i]
        if robot:isClose() then 
            return robot
        end
    end
    --没有空的就创建
    self:createRobot(1)   
    return self.robot_pool[#self.robot_pool]
end


--一个定时驱动逻辑
function RobotManager:update(dt)    
	for i=1, #self.robot_pool do 
    	self.robot_pool[i]:update(uid)
	end
    self.delay = self.delay + dt
    if self.delay > self.show_vip_time then 
        self.delay = 0
        self.show_vip_time = math_random(30, 120)
        local uid 
        local res
        repeat
            --todo
            uid = table_remove(self.vip_list)
            res = self:ntPlayerEnter(uid)
        until res or not next(self.vip_list)            

    end
end

--排下序，有座有钱的优先
function RobotManager:sortRobot()
    local function sortFunc(a, b)
        if not a.close and b.close then 
            return true
        elseif a.close and not b.close then 
            return false
        elseif not a.close and not b.close then 
            if a.user.seat_id ~= b.user.seat_id then 
                return a.user.seat_id > b.user.seat_id
            end            
            return a.user:getCoins() > b.user:getCoins()
        else
            return false
        end
    end
    table_sort( self.robot_pool, sortFunc )
end


--删除机器人
function RobotManager:removeRobot(uid)	
    self.robot_list[uid] = nil
    self.message_list[uid] = nil
	R().robotmgr(1):send('.msg_handler','put_back_robots',{{type=self.robot_type,uid=uid,coins=0}})	
end

--删除所有
function RobotManager:removeAll()  
    local robots = {}
    for uid, v in pairs(self.robot_list) do             
        table.insert(robots, {type=self.robot_type,uid=uid,coins=0})
    end
    self.robot_list = {}
    self.message_list = {}
    R().robotmgr(1):send('.msg_handler','put_back_robots', robots)    
end


--指定类型机器人所剩余的金币总和
--robot_type 机器类型id
function RobotManager:getTotalCoins(robot_type_id)    
    return self.total_coins_list[robot_type_id] or 0
end

--设置各个类型机器人能下注的总和
function RobotManager:setTotalCoins()    
    local robot_type_list = self.room_config:getRobotTypeList()
    for i=1, #robot_type_list do 
        local user_list = self.user_manager:getRobotList(i)        
        local coins = 0
        for _, user in pairs(user_list) do 
            local uid = user:getUid()
            local robot = self.robot_list[uid]
            if robot and robot:getCanBet() then --这局能下注的才算
                coins = user:getCoins() + coins
            end
        end
        self.total_coins_list[i] = coins
    end
    -- dbglog("__total_coins_list______2________",self.total_coins_list)
end

--获取每种类型的机器人可下注总额度
function RobotManager:getCanBetCoins(robot_type_id)    
    if not robot_type_id then 
        return 0
    end    
    local last_player_betting_coins = 0
    local config = self.room_config:getRobotConfig(robot_type_id) --robot.lua配置    
    local last_bet_rate = config.system_last_bet_rate / 100  --上局下注选用比例
    local bet_min = config.system_bet_min +  (last_player_betting_coins or 0) * last_bet_rate   --机器人下注下限    
    local bet_float = string_split(config.bet_area_float, '-')
    local float_num = math_random(tonumber(bet_float[1]),tonumber(bet_float[2]))       
    local total_bet = math_floor(bet_min * (float_num / 100))
    return total_bet
end

-- function RobotManager:getRobotList()
--     local users = {}
--     for uid, robot in pairs(self.robot_list) do 
--         if not robot:isClose() and not robot:isBanker() then 
--             table_insert(users, robot:getUser())
--         end
--     end
--     return users
-- end

function RobotManager:getRobotsList(min_coins)
    local users = {}
    for uid, robot in pairs(self.robot_list) do 
        dbglog("getRobotsList coins",robot:getCoins(),"min_coins:",min_coins)
        if not robot:isClose() and not robot:isBanker() and robot:getCoins() >= min_coins then 
            table_insert(users, robot)
        end
    end
    return users
end


--vip玩家入桌时的推送
function RobotManager:ntPlayerEnter(uid)
    if not uid then 
        return 
    end
    local user = self.user_manager:getUser(uid)
    if not user then 
        return
    end
    local play_effect = false    
    -- user.vip_level = 3
    local enter_word = self.room_config:canPlayEffect(user:getVipLevel()) 
    if enter_word then
        play_effect = true
    else
        enter_word = nil
    end
    -- if user:getBeted() then --下注过就是断线重连
    --     play_effect = false
    -- end    
    --入场动画
    local data = {play_effect=play_effect, player=user:getClientInfo(), enter_word=enter_word}
    print("vip机器人进入________",uid)
    self.desk:sendToAllUser('table.NTF_PLAYER_ENTER', data)
    return true
end

return RobotManager